package com.sunyur.tailor.channel.common.inner.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.sunyur.tailor.channel.common.inner.base.SunyurListResult;
import com.sunyur.tailor.channel.common.inner.base.SunyurResult;
import com.sunyur.tailor.channel.common.middle.enums.MiddleResultEnum;
import com.sunyur.tailor.channel.common.middle.util.SignUtil;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @Author 99288
 * @Description 商越客户端
 * @Date 11:50 2021/1/11
 * @Param
 * @return
 **/
@Configuration
public class SunyurClientUtil {
	private static final Logger LOGGER_INFO = LoggerFactory.getLogger(SunyurClientUtil.class);
	private static final Logger LOGGER_ERROR = LoggerFactory.getLogger(SunyurClientUtil.class);

	@Autowired
	private HttpClient httpClient;

	@Value("${sunyur.key}")
	private String sunyurKey;

	@Value("${sunyur.secret}")
	private String sunyurSecret;

	@Value("${sunyur.domain}")
	private String sunyurDomain;

	/**
	 *
	 * @Author 99288
	 * @Description POST 请求
	 * @Date 15:46 2021/1/11
	 * @Param
	 * @return
	 **/
	public <T> SunyurResult execPost(String path, String requestBody, TypeReference<SunyurResult<T>> typeReference){
		LOGGER_INFO.info("SunyurClient execPost path：{}, requestBody：{}", path, requestBody);
		SunyurResult result = new SunyurResult();
		HttpPost httpPost = new HttpPost(sunyurDomain + path);
		this.addHeader(path, requestBody, httpPost);
		httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
		HttpResponse httpResponse;
		String responseBody;
		try {
			httpResponse = httpClient.execute(httpPost);
			responseBody = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
		} catch (IOException e) {
			LOGGER_ERROR.error("SunyurClient execPost exception:{}", e);
			result.setErrorMessage(MiddleResultEnum.EXCEPTION.getCode(), e.getMessage());
			return result;
		}
		LOGGER_INFO.info("SunyurClient execPost path：{}, responseBody:{}", path, responseBody);
		if (httpResponse.getStatusLine().getStatusCode() == 200) {
			if (Objects.isNull(typeReference)) {
				result = JSON.parseObject(responseBody, SunyurResult.class);
			}else {
				result = JSON.parseObject(responseBody, typeReference);
			}
			return result;
		} else {
			httpPost.abort();
			result.setErrorMessage(MiddleResultEnum.FAILED.getCode(), MiddleResultEnum.FAILED.getValue());
		}
		return result;
	}

	/**
	 * @description 返回分页集合
	 * @param path
	 * @param requestBody
	 * @return com.sunyur.tailor.channel.common.inner.base.SunyurResult
	 * @author yu.chen
	 * @date 2021/4/28 22:18
	 * @Version v1.0
	 */
	public <T> SunyurListResult execListPost(String path, String requestBody, TypeReference<SunyurListResult<T>> typeReference){
		LOGGER_INFO.info("SunyurClient execListPost path：{}, requestBody：{}", path, requestBody);
		SunyurListResult result = new SunyurListResult();
		HttpPost httpPost = new HttpPost(sunyurDomain + path);
		this.addHeader(path, requestBody, httpPost);
		httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
		HttpResponse httpResponse;
		String responseBody;
		try {
			httpResponse = httpClient.execute(httpPost);
			responseBody = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
		} catch (IOException e) {
			LOGGER_ERROR.error("SunyurClient execListPost exception:{}", e);
			result.setErrorMessage(MiddleResultEnum.EXCEPTION.getCode(), e.getMessage());
			return result;
		}
		LOGGER_INFO.info("SunyurClient execListPost path：{}, responseBody:{}", path, responseBody);
		if (httpResponse.getStatusLine().getStatusCode() == 200) {
			if (Objects.isNull(typeReference)) {
				result = JSON.parseObject(responseBody, SunyurListResult.class);
			}else {
				result = JSON.parseObject(responseBody, typeReference);
			}
			result.setContent(result.getContent());
			return result;
		} else {
			httpPost.abort();
			result.setErrorMessage(MiddleResultEnum.FAILED.getCode(), MiddleResultEnum.FAILED.getValue());
		}
		return result;
	}

	/**
	 *
	 * @Author 99288
	 * @Description POST byte请求
	 * @Date 17:05 2021/1/11
	 * @Param
	 * @return
	 **/
	public SunyurResult<byte[]> execFilePost(String path, String requestBody) throws Exception {
		LOGGER_INFO.info("SunyurClient execFilePost path：{}, requestBody：{}", path, requestBody);
		SunyurResult<byte[]> result = new SunyurResult();
		HttpPost httpPost = new HttpPost(sunyurDomain + path);
		httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
		this.addHeader(path, requestBody, httpPost);
		HttpResponse httpResponse = httpClient.execute(httpPost);
		byte[] bytes = EntityUtils.toByteArray(httpResponse.getEntity());
		LOGGER_INFO.info("SunyurClient execFilePost path：{}, responseBody:{}", path, bytes);
		if (httpResponse.getStatusLine().getStatusCode() == 200) {
			result.setContent(bytes);
			return result;
		} else {
			httpPost.abort();
			result.setErrorMessage(String.valueOf(httpResponse.getStatusLine().getStatusCode()), "request is fail");
		}
		return result;
	}


	/**
	 *
	 * @Author 99288
	 * @Description GET请求
	 * @Date 17:05 2021/1/11
	 * @Param
	 * @return
	 **/
	public <T> SunyurResult execGet(String path, String requestBody, TypeReference<SunyurResult<T>> typeReference){
		LOGGER_INFO.info("SunyurClient execGet path：{}, requestBody：{}", path, requestBody);
		HttpGet http = new HttpGet(sunyurDomain + path);
		SunyurResult result = new SunyurResult();
		this.addHeader(path, requestBody, http);
		HttpResponse httpResponse;
		String responseBody;
		try {
			httpResponse = httpClient.execute(http);
			responseBody = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
		} catch (IOException e) {
			LOGGER_ERROR.error("SunyurClient execGet exception:{}", e);
			result.setErrorMessage(MiddleResultEnum.EXCEPTION.getCode(), e.getMessage());
			return result;
		}
		LOGGER_INFO.info("SunyurClient execGet path：{}, responseBody:{}", path, responseBody);
		if (httpResponse.getStatusLine().getStatusCode() == 200) {
			if (Objects.isNull(typeReference)) {
				result = JSON.parseObject(responseBody, SunyurResult.class);
			}else {
				result = JSON.parseObject(responseBody, typeReference);
			}
			result.setContent(result.getContent());
			return result;
		} else {
			result.setErrorMessage(MiddleResultEnum.FAILED.getCode(), MiddleResultEnum.FAILED.getValue());
		}
		return result;
	}

	/**
	 *
	 * @Author 99288
	 * @Description 组装header
	 * @Date 16:43 2021/1/11
	 * @Param
	 * @return
	 **/
	private void addHeader(String path, String requestBody, HttpRequestBase http) {
		http.addHeader("X-Ca-Key", sunyurKey);
		http.addHeader("X-Ca-Timestamp", String.valueOf(System.currentTimeMillis()));
		http.addHeader("Content-Type", "application/json;charset=UTF-8");
		Map<String, String> headers = new HashMap<>();
		for (Header header : http.getAllHeaders()) {
			headers.put(header.getName(), header.getValue());
		}
		String sign = SignUtil.sign(sunyurSecret, http.getMethod(), path, headers, requestBody);
		http.addHeader("X-Ca-Signature", sign);
	}
}